package seismosurfer.domain;

import java.sql.SQLException;

import seismosurfer.data.UserData;
import seismosurfer.database.DB;
import seismosurfer.database.UserDAO;
import seismosurfer.util.EmailService;
import seismosurfer.util.Notification;
import seismosurfer.util.Util;

/**
 * Provides operations for user management.
 *
 */
public class User extends DomainObject {

    /** The GUEST role. */
    public static final String GUEST = "guest";
    
    /** The SURFER role. */
    public static final String SURFER = "surfer";
    
    /** The MINER role. */
    public static final String MINER = "miner";
    
    /** The ADMIN role. */
    public static final String ADMIN = "admin";

    public static final String MISSING_NICKNAME = "Nick name is missing.";

    public static final String DUPLICATE_NICKNAME = "Nick name already exists.";

    public static final String MISSING_USERNAME = "Email is missing.";

    public static final String DUPLICATE_USERNAME = "Email already exists.";

    public static final String UNKNOWN_USERNAME = "Email is unknown .";

    public static final String MISSING_PASSWORD = "Password is missing.";

    public static final String WRONG_SPELLING = "Passwords don`t match.";

    public static final String MISSING_COUNTRY = "Country is missing.";

    public static final String UNKNOWN_COUNTRY = "Country is unknown .";
    

    private UserData user = (UserData) data;
    
    /**
     * Creates a user given her data.
     * 
     * @param user the UserData that contains
     *        this user`s data.
     */
    public User(UserData user) {
        super(user);
    }
    
    /**
     * Sends an email to a user with the given username.
     * 
     * @param username the name of the user who is going
     *        to be sent an email
     * @return a Notification which contains possible errors.
     */
    public static Notification sendEmail(String username) {
        Notification err = new Notification();

        if (Util.isNullOrBlank(username)) {
            err.put(USERNAME, MISSING_USERNAME);
            return err;
        }
        UserData ud = UserDAO.findUser(USERNAME, username);
        if (ud == null) {
            err.put(USERNAME, UNKNOWN_USERNAME);
            return err;
        }

        EmailService.send(ud.getUserName(), ud.getPassword());

        return err;
    }
    
    /**
     * Registers this user.
     * 
     * @return true if the registration was successful
     */
    public boolean registerUser() {
        // this should be put in a transaction
        try {
            DB.begin();
            validate();

            if (!user.getNotification().hasErrors()) {
                UserDAO.insert(user);
                UserDAO.insertUserRole(user.getUserName(), SURFER);

                DB.commit();
                return true;
            }

            DB.rollback();
            return false;
        } catch (SQLException ex) {
            DB.handleTransactionError(ex);
            return false;
        }
    }

    private void validate() {
        // nickname
        boolean failed = failIfNullOrBlank(user.getNickName(), NICKNAME,
                MISSING_NICKNAME);

        if (!failed) {
            fail(UserDAO.findUser(NICKNAME, user.getNickName()) != null,
                    NICKNAME, DUPLICATE_NICKNAME);
        }

        // email (username)
        failed = failIfNullOrBlank(user.getUserName(), USERNAME,
                MISSING_USERNAME);

        if (!failed) {
            fail(UserDAO.findUser(USERNAME, user.getUserName()) != null,
                    USERNAME, DUPLICATE_USERNAME);
        }

        // password
        failIfNullOrBlank(user.getPassword(), PASSWORD, MISSING_PASSWORD);

    }
}